package com.learning.optimize.jdk.classloader;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.util.Date;

/**
 * ClassName: CustomClassLoader
 * Description: 自定义类加载器
 * Date: 2018/7/17 15:01 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class CustomClassLoader extends ClassLoader {

    /**
     * 类的加载路径
     */
    private String classPath;
    /**
     * 类加载器的名字
     */
    private String name;

    public CustomClassLoader() {
    }

    public CustomClassLoader(String classPath, String name) {
        this.classPath = classPath;
        this.name = name;
    }

    /**
     * 重写 loadClass() 方法，打破委托机制
     *
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // loadClass() 方法会去 父类委托，然后再找自己，调用findClass()方法
        return super.loadClass(name);
    }

    /**
     * 重写 findClass() 方法，先让父类树处理，然后自己处理，继承了委托机制
     *
     * @param name
     * @return
     */
    @Override
    protected Class<?> findClass(String name) {
        String classFileName = classPath + name + ".class";
        try {
            FileInputStream fis = new FileInputStream(classFileName);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            cypher(fis, bos);
            fis.close();
            byte[] bytes = bos.toByteArray();
            return defineClass(null, bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *
     *
     * @param ips
     * @param ops
     */
    private static void cypher(InputStream ips, OutputStream ops) {
        int b;
        try {
            while ((b = ips.read()) != -1) {
                ops.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    public static void main(String[] args) throws Exception {

        CustomClassLoader classLoader = new CustomClassLoader("/WorkSpace/Sam/Learning/Learning-JavaOptimize/Java-JDK/target/classes/com/learning/optimize/jdk/classloader/", "CustomClassLoader");
        Class<?> clazz = classLoader.loadClass("CustomClassLoaderAttachment");
        System.out.println(clazz.getClassLoader().getClass().getName());

        Constructor<?> constructor = clazz.getConstructor(String.class);
        Date attachment = (Date) constructor.newInstance("名字");
        System.out.println(attachment);
    }

    /*
    * 输出：
        com.learning.optimize.jdk.classloader.CustomClassLoader
        CustomClassLoaderAttachment{name='名字'}
    */
}
